stringbuf sb; istream is(&sb);有了流对象我们就可以在流上进行各种输入输出操作,输入会从缓冲区读数据,输出会将数据写到缓冲区。 注意对缓冲区的读写一定要注意方法,流符号是格式化输入输出,get、put、read、write等是二进制读写。 格式化输入的内容应当格式化读取,二进制写入应当二进制读取,否则会出现写入和读出数据不一致的问题。 格式化写入一个int 数据时,会将该数据每位分离出来,按照字符编码写到缓冲区,例如 int x= 123, 格式化写入以后缓冲区存以后,缓冲区有三个字节分别存放1、2、3的字符编码。格式化读出是相反的过程,将读到的字符转成相应的类型的数据。 二进制写入时进行直接的内存拷贝不做任何动作,例如 int x = 123 二进制写入后(二进制写时需要取地址,转成char* 并指出要写入的字节数,如f.write((char*)&x,sizeof(int))。 写完后缓冲区的数据是0x0000007b,是计算机内存中对123 的内存的完全拷贝。 下面是缓冲区使用的情景: 考虑一个生产者、消费者的问题,线程A生成的数据,线程B读取,可以解决的方案如下: 1 设立全局变量缓冲数据,A、B都可以访问(在这种情况下,A 生产的时候要考虑缓冲区是否够用,B读取的时候要判断当前是否有有效数据可读,而且很难设计一个合理分配内存的缓冲区(想象A生产的数据有时很大,有时很小))。 2 网络通信(TCP、UDP) 3 streambuf 登场,有了streambuf配合stream,A就像正常操作流一样往流对象里塞数据,而B 就像正常操作流一样从流里面读数据,不用关心其他问题,只要这两个流的sterambuf 是同一个对象。 一段代码实例:
#include <iostream> #include <streambuf> #include <sstream> #include <fstream> #include <string> #include <cstring> #include <memory> #include <thread> using namespace std; stringbuf buf; istream in(&buf); ostream out(&buf); bool flag = false; void threadb() { char data; while (true) { if (flag) { in >> data; cout << "thread B recv:" << data << endl; flag = false; } } } int main() { thread consumer(threadb); char data; while (true) { cin >> data; out << data; flag = true; } return 0; }output:
abc thread B recv:a def thread B recv:b 1 thread B recv:c 1 thread B recv:d在特殊的情景下可以实现自己的streambuf类,自己实现的类必须继承streambuf 类,自定义的streambuf 必须实现overflow、underflow、uflow 等方法,其中overflow在输出缓冲区不够用时调用,underflow和uflow在输入缓冲区无数据时调用,区别是uflow 会让读取位置前进一位,而underflow不会。sreambuf 内部维护着六个指针 eback、gptr、egptr、pbase、pptr、epptr,分别指向读取缓冲区的头、当前读取位置、尾、写缓冲区的头、当前写位置、尾(实际上这几个指针指向同一段缓冲区)。 自定义实现方式要注意要在该返回EOF的时候,返回EOF,underflow和uflow都有可能返回EOF,一旦返回了EOF则标志着流结束,之后对流的操作无效。 如下代码实现了一个自定义的streambuf:
#include <iostream> #include <streambuf> #include <sstream> #include <fstream> #include <string> #include <cstring> #include <memory> using namespace std; class mybuf : public streambuf { public: enum{ SIZE = 10}; mybuf() { memset(buffer, 'j', 10); //buffer[3] = ' '; setbuf(buffer, SIZE); } void log() { cout <<hex<<gptr() << endl; } protected: int_type overflow( int_type c) { cout << "overflow" << endl; return c; } streambuf* setbuf(char* s, streamsize n) { setp(s, s + n); setg(s, s, s + n); return this; } int_type underflow() override{ cout << "here"<<endl; memset(buffer, 'w', 10); setg(buffer, buffer, buffer+10); return ' '; } int_type uflow() override{ cout << "uflow" << endl; memset(buffer, 'x', 10); setg(buffer, buffer, buffer + 10); return EOF; } private: char buffer[SIZE]; }; int main() { mybuf buf; char test[2000]; memset(test, 'a', 2000); //buf.pubsetbuf(test, 1000); string hh; string xx; istream in(&buf); ostream tt(&buf); in>>hh; cout << hh << endl; //tt.write(test, 9); in >> xx; in.read(test, 11); cout<< xx << endl; cout << "end" << endl; return 0; } /* here jjjjjjjjjj here uflow wwwwwwwwww end */
本页共150段,4448个字符,7576 Byte(字节)